package com.weilele.mvvm.utils.activity

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.telephony.PhoneNumberFormattingTextWatcher
import android.text.*
import android.text.method.HideReturnsTransformationMethod
import android.text.method.LinkMovementMethod
import android.text.method.PasswordTransformationMethod
import android.text.style.*
import android.text.style.ImageSpan
import android.util.DisplayMetrics
import android.util.TypedValue
import android.view.*
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.PopupWindow
import android.widget.TextView
import androidx.annotation.*
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.view.children
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentContainerView
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.bumptech.glide.Glide
import com.google.android.material.badge.BadgeDrawable
import com.google.android.material.badge.BadgeUtils
import com.google.android.material.badge.ExperimentalBadgeUtils
import com.google.android.material.internal.ToolbarUtils
import com.weilele.mvvm.adapter.ignoreError
import com.weilele.mvvm.app
import com.weilele.mvvm.base.helper.SingleClickListener
import com.weilele.mvvm.utils.`object`.ScreenAdaptationObj
import com.weilele.mvvm.view.GestureDetectorHelper


/**
 * 描述：view扩展方法
 */

data class SpanBean(
    var text: String?,/*要改变的文本效果*/
    var textColor: Int? = null,/*文字颜色*/
    var textSize: Int? = null,/*文字大小*/
    var textClickListener: Function1<View, Unit>? = null,/*文字点击*/
    var typeface: Int? = null,/*eg:[Typeface.BOLD_ITALIC]*/
    var url: Pair<String?, View.OnClickListener?>? = null,/*Pair<"https://baidu.com",listener>*/
    var drawable: Drawable? = null,/*设置图片的话，文字将会失效*/
    var isUnderlineText: Boolean? = null,/*是否需要下划线*/
    var strikethroughSpan: Boolean? = null,/*删除线*/
    var backgroundColor: Int? = null,/*背景色*/
    var spanWhatList: MutableList<CharacterStyle>? = null,/*支持其他未被定义的CharacterStyle*/

)

inline fun <reified T : Activity> View?.getActivity(): T? {
    return this?.context.toActivity()
}

fun View?.getActivity(): AppCompatActivity? {
    return this?.context.toActivity()
}

fun View?.getLifecycleOwner(): LifecycleOwner? {
    return this?.findFragment() ?: getActivity()
}

/**
 * 设置文本颜色
 */
infix fun TextView?.setTextResColor(@ColorRes colorRes: Int) {
    this?.setTextColor(getResColor(colorRes))
}

infix fun TextView?.setTextStringColor(colorStr: String?) {
    colorStr ?: return
    this?.setTextColor(Color.parseColor(colorStr))
}

/**
 * 设置textView从资源文件
 */
infix fun TextView?.textFrom(@StringRes strRes: Int?) {
    this ?: return
    strRes ?: return
    text = try {
        this.context.getText(strRes)
    } catch (e: Throwable) {
        strRes.toString()
    }
}

/**
 * 设置textView从资源文件
 */
infix fun TextView?.textFrom(str: CharSequence?) {
    this?.text = str
}

fun View?.onClick(clickSpace: Long? = null, onSingleClick: Function1<View, Unit>?) {
    this?.setOnClickListener(
        if (onSingleClick == null) null else SingleClickListener(
            clickSpace,
            onSingleClick
        )
    )
}

//    tv.textFromSpanBean(mutableListOf(
//                SpanBean("这个"),
//                SpanBean("百度", url = Pair("https://baidu.com", null), textColor = Color.BLUE),
//                SpanBean("百123", drawable = getResDrawable(R.drawable.scroll_to_top)),
//                SpanBean("真的好垃圾", typeface = Typeface.BOLD_ITALIC),
//                SpanBean("下划线", typeface = Typeface.BOLD_ITALIC, textColor = Color.RED, underlineSpan = UnderlineSpan()),
//                SpanBean("删除线", typeface = Typeface.BOLD_ITALIC, textColor = Color.RED, underlineSpan = UnderlineSpan(),
//                        strikethroughSpan = StrikethroughSpan()),
//        ))
infix fun TextView?.textFromSpanBean(textList: MutableList<SpanBean>) {
    this ?: return
    val ssb = SpannableStringBuilder()
    textList.forEach {
        if (it.text != null) {
            val sbText = SpannableStringBuilder(it.text)
            /**
             * 设置url
             */
            it.url?.first?.let { url ->
                movementMethod = LinkMovementMethod.getInstance()
                sbText.setSpan(object : URLSpan(url) {
                    override fun onClick(widget: View) {
                        super.onClick(widget)
                        val listener = it.url?.second
                        if (listener == null) {
                            widget.context.goToWeb(url)
                        } else {
                            listener.onClick(widget)
                        }
                    }
                }, it)
            }
            /**
             * 设置图片
             */
            it.drawable?.let { drawable ->
                drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
                val span = ImageSpan(drawable, ImageSpan.ALIGN_BASELINE)
                it.text = "0"
                sbText.clear()
                sbText.append(it.text)
                sbText.setSpan(span, it)
            }
            /**
             * 如果点击不为null，则按照下面方式这是文字颜色和下划线
             */
            if (it.textClickListener != null) {
                it.textClickListener?.let { click ->
                    //这个一定要记得设置，不然点击不生效
                    movementMethod = LinkMovementMethod.getInstance()
                    sbText.setSpan(object : ClickableSpan() {
                        override fun onClick(widget: View) {
                            click.invoke(widget)
                        }

                        override fun updateDrawState(ds: TextPaint) {
                            super.updateDrawState(ds)
                            it.textColor?.let {
                                ds.color = it
                            }
                            it.isUnderlineText?.let {
                                ds.isUnderlineText = it
                            }
                        }
                    }, it)
                }
            } else {
                it.textColor?.let { textColor ->
                    sbText.setSpan(object : ForegroundColorSpan(textColor) {
                        override fun updateDrawState(textPaint: TextPaint) {
                            super.updateDrawState(textPaint)
                            it.isUnderlineText?.let {
                                textPaint.isUnderlineText = it
                            }
                        }
                    }, it)
                }
            }

            /**
             * 文字大小
             */
            it.textSize?.let { textSize ->
                sbText.setSpan(AbsoluteSizeSpan(textSize, true), it)
            }
            /**
             * 文字样式
             */
            it.typeface?.let { typeface ->
                sbText.setSpan(StyleSpan(typeface), it)
            }
            /**
             * 删除线
             */
            if (it.strikethroughSpan == true) {
                sbText.setSpan(StrikethroughSpan(), it)
            }
            /**
             * 背景色
             */
            it.backgroundColor?.let { backgroundColor ->
                sbText.setSpan(BackgroundColorSpan(backgroundColor), it)
            }
            /**
             * 其他span
             */
            it.spanWhatList?.forEach { what ->
                sbText.setSpan(what, it)
            }
            ssb.append(sbText)
        }
    }
    text = ssb
    //想去掉点击后文字背景，设置一下HighlightColor即可
    highlightColor = Color.TRANSPARENT
}

private fun SpannableStringBuilder.setSpan(what: CharacterStyle, spanBean: SpanBean) {
    val text = spanBean.text ?: return
    setSpan(what, 0, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}


/**
 * view隐藏
 */
fun View?.gone() {
    this ?: return
    if (visibility != View.GONE) {
        visibility = View.GONE
    }
}

/**
 * 通过变量控制是否隐藏
 */
fun View?.setGone(visible: Boolean) {
    this ?: return
    if (visible) {
        visible()
    } else {
        gone()
    }
}

/**
 * 通过变量控制是否隐藏
 */
fun View?.setInvisible(visible: Boolean) {
    this ?: return
    if (visible) {
        visible()
    } else {
        invisible()
    }
}

/**
 * view可见
 */
fun View?.visible() {
    this ?: return
    if (visibility != View.VISIBLE) {
        visibility = View.VISIBLE
    }
}

/**
 * view隐藏
 */
fun View?.invisible() {
    this ?: return
    if (visibility != View.INVISIBLE) {
        visibility = View.INVISIBLE
    }
}

/**
 * view是否可见
 */
fun View?.isVisible(): Boolean {
    this ?: return false
    return visibility == View.VISIBLE
}

/**
 * view是否可见
 */
fun View?.isInVisible(): Boolean {
    this ?: return true
    return visibility == View.INVISIBLE
}

/**
 * view是否隐藏
 */
fun View?.isGone(): Boolean {
    this ?: return true
    return visibility == View.GONE
}

/**
 * dp2px
 */
fun dip(value: Int): Int {
    return (value * ScreenAdaptationObj.density).toInt()
}

fun dip(value: Double): Double {
    return value * ScreenAdaptationObj.density
}

fun sp(value: Float): Float {
    return (value * ScreenAdaptationObj.scaledDensity)
}

/**
 * dp2px
 */
fun dip(value: Float): Float {
    return value * ScreenAdaptationObj.density
}

val Int.dp: Int
    get() = dip(this)

val Float.dp: Float
    get() = dip(this)

val Double.dp: Double
    get() = dip(this)

val Int.sp: Int
    get() = sp(this.toFloat()).toInt()

val Float.sp: Float
    get() = sp(this)

val Double.sp: Double
    get() = sp(this.toFloat()).toDouble()

fun Any?.sp2Px(value: Float): Float {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value, requireDisplayMetrics())
}

fun Any?.dp2Px(value: Float): Float {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, requireDisplayMetrics())
}

fun Any?.dp2Px(value: Int): Int {
    return dp2Px(value.toFloat()).toInt()
}

fun Any?.requireDisplayMetrics(): DisplayMetrics {
    return when (this) {
        is Context -> {
            this.resources.displayMetrics
        }
        is View -> {
            this.resources.displayMetrics
        }
        is Fragment -> {
            this.resources.displayMetrics
        }
        is PopupWindow -> {
            (this.contentView?.resources ?: app.resources).displayMetrics
        }
        else -> {
            app.resources.displayMetrics
        }
    }
}

fun ViewGroup.inflate(@LayoutRes id: Int, isAttach: Boolean = false): View {
    return LayoutInflater.from(this.context).inflate(id, this, isAttach)
}

/**
 * 设置textView从资源文件
 */
@SuppressLint("RtlHardcoded")
fun TextView?.setIcon(
    @DrawableRes drawableRes: Int?, gravity: Int = Gravity.START,
    drawablePaddingDip: Int = -1
) {
    this ?: return
    if (drawableRes == null) {
        setCompoundDrawables(null, null, null, null)
        return
    }
    val drawable = context.getResDrawable(drawableRes)
    setIcon(drawable, gravity, drawablePaddingDip)
}

fun TextView?.setIcon(
    drawable: Drawable?, gravity: Int = Gravity.START,
    drawablePaddingDip: Int = -1
) {
    this ?: return
    if (drawable == null) {
        setCompoundDrawables(null, null, null, null)
        return
    }
    drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
    if (drawablePaddingDip >= 0) {
        compoundDrawablePadding = dip(drawablePaddingDip)
    }
    when (gravity) {
        Gravity.TOP -> {
            setCompoundDrawables(null, drawable, null, null)
        }
        Gravity.BOTTOM -> {
            setCompoundDrawables(null, null, null, drawable)
        }
        Gravity.END, Gravity.RIGHT -> {
            setCompoundDrawables(null, null, drawable, null)
        }
        else -> {
            setCompoundDrawables(drawable, null, null, null)
        }
    }
}

/**
 * 监听文本输入之后
 */
fun EditText?.afterTextChanged(onAfterTextChanged: Function1<Editable?, Unit>) {
    this ?: return
    addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            onAfterTextChanged.invoke(s)
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        }

    })
}

/**
 * 文本输入之前监听
 */
fun EditText?.beforeTextChanged(beforeTextChanged: (s: CharSequence?, start: Int, count: Int, after: Int) -> Unit) {
    this ?: return
    addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            beforeTextChanged.invoke(s, start, count, after)
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        }

    })
}

/**
 * 文本改变监听
 */
fun EditText?.onTextChanged(onTextChanged: (s: CharSequence?, start: Int, before: Int, count: Int) -> Unit) {
    this ?: return
    addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            onTextChanged.invoke(s, start, before, count)
        }

    })
}

/**
 * 指定搜索键并支持触发
 */
fun EditText?.onSearch(isHideKeyboard: Boolean = true, search: (text: String) -> Unit) {
    this.onAction(EditorInfo.IME_ACTION_SEARCH, isHideKeyboard, search)
}

fun EditText?.onAction(
    imeOptions: Int,
    isHideKeyboard: Boolean = true,
    search: (text: String) -> Unit
) {
    this?.imeOptions = imeOptions
    this?.setSingleLine()
    this?.setOnEditorActionListener { v, actionId, event ->
        if (actionId == imeOptions) {
            val ctx = context
            if (isHideKeyboard && ctx is Activity) {
                ctx.hiddenKeyboard()
            }
            search.invoke(v.text.toString())
            return@setOnEditorActionListener true
        }
        return@setOnEditorActionListener true
    }
}

/**
 * 设置最大长度
 */
fun EditText?.setMaxLength(max: Int) {
    addFilters(InputFilter.LengthFilter(max))
}

/**
 * 所有字母大写
 */
fun EditText?.allCaps() {
    addFilters(InputFilter.AllCaps())
}

/**
 * 在之前的基础上，新增一个或者多个InputFilter
 */
fun EditText?.addFilters(vararg filter: InputFilter) {
    this ?: return
    if (filter.isNullOrEmpty()) {
        return
    }
    val old = this.filters
    val new = arrayOf<InputFilter>(*old, *filter)
    this.filters = new
}

/**
 * 有时候，我们的需求，需要收入手机号码的时候，
 * 需用空格分开(133 3333 3333)
 */
fun EditText?.phoneNumberFormattingTextWatcher() {
    this?.addTextChangedListener(PhoneNumberFormattingTextWatcher())
}


/**
 * 密码可见不可见
 */
fun EditText?.visiblePassword(visible: Boolean) {
    this ?: return
    transformationMethod = if (visible) {
        //选择状态 显示明文--设置为可见的密码
        //mEtPassword.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
        HideReturnsTransformationMethod.getInstance()
    } else {
        //默认状态显示密码--设置文本 要一起写才能起作用 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD
        //mEtPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
        PasswordTransformationMethod.getInstance()
    }
    setSelection(text.count())
}

/**
 * 设置双击监听
 * 注意GestureDetectorHelper对于同一个view对象只能创建一次
 * 如果不想响应单击，可以这样使用
 *  @sample{
 *   GestureDetectorHelper(view, true).apply {
 *   setOnDoubleClickListener {
 *     //双击
 *      }
 *      setOnClickListener {
 *       //单击
 *    }
 *   }
 *  }
 */
fun View?.setOnDoubleClickListener(l: Function1<MotionEvent?, Unit>) {
    this ?: return
    GestureDetectorHelper(this, true).setOnDoubleClickListener(l)
}

/**
 * 是否已经滚动到顶部
 */
fun View?.hadScrollToTop(): Boolean {
    this ?: return false
    return !this.canScrollVertically(-1)
}

/**
 * 是否已经滚动到底部
 */
fun View?.hadScrollToBottom(): Boolean {
    this ?: return false
    return !this.canScrollVertically(1)
}

/**
 * 是否已经滚动到左边
 */
fun View?.hadScrollToStart(): Boolean {
    this ?: return false
    return !this.canScrollHorizontally(-1)
}

/**
 * 是否已经滚动到右边
 */
fun View?.hadScrollToEnd(): Boolean {
    this ?: return false
    return !this.canScrollHorizontally(1)
}

/**
 * glide 优化recyclerView
 */
fun RecyclerView.enableAutoGlideLoad() {
    this.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        var sIsScrolling = false
        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            super.onScrollStateChanged(recyclerView, newState)
            if (newState == RecyclerView.SCROLL_STATE_DRAGGING || newState == RecyclerView.SCROLL_STATE_SETTLING) {
                if (!sIsScrolling) {
                    if (!Glide.with(this@enableAutoGlideLoad).isPaused) {
                        Glide.with(this@enableAutoGlideLoad).pauseRequests()
                    }
                }
                sIsScrolling = true
            } else if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                if (sIsScrolling) {
                    if (Glide.with(this@enableAutoGlideLoad).isPaused) {
                        Glide.with(this@enableAutoGlideLoad).resumeRequests()
                    }
                }
                sIsScrolling = false
            }
        }
    })
}

/**
 * 查找view所依赖的fragment
 */
fun <F : Fragment> View.findFragment(): F? {
    return ignoreError { FragmentManager.findFragment(this) }
}

/**
 * 获取与FragmentContainerView绑定的fg
 */
fun <F : Fragment> FragmentContainerView?.getBindFragment(fragment: Fragment?): F? {
    this ?: return null
    return fragment?.childFragmentManager.findFragment(this.id)
}

fun <F : Fragment> FragmentContainerView?.getBindFragment(activity: AppCompatActivity?): F? {
    this ?: return null
    return activity?.supportFragmentManager.findFragment(this.id)
}

/**
 * 根据id查找fragment
 */
fun <F : Fragment> FragmentManager?.findFragment(@IdRes id: Int): F? {
    return this?.findFragmentById(id) as? F
}

@SuppressLint("ClickableViewAccessibility")
fun View.scaleAnimByTouchListener() {
    setOnTouchListener { v, event ->
        v.scaleAnimByMotionEvent(event)
        false
    }
}

fun View.scaleAnimByMotionEvent(
    ev: MotionEvent?,
    smallScale: Float = 0.8f,
    bigScale: Float = 1f,
    build: ((ViewPropertyAnimator) -> Boolean)? = null
) {
    when (ev?.action) {
        MotionEvent.ACTION_DOWN -> {
            startScaleAnim(smallScale, build)
        }
        MotionEvent.ACTION_UP,
        MotionEvent.ACTION_CANCEL -> {
            startScaleAnim(bigScale, build)
        }
    }
}

fun View.startScaleAnim(
    endScale: Float,
    build: ((ViewPropertyAnimator) -> Boolean/*返回true，需要手动调用start()*/)?
) {
    animate().cancel()
    pivotX = width.toFloat() / 2
    pivotY = height.toFloat() / 2
    val anim = animate()
        .scaleX(endScale)
        .scaleY(endScale)
        .setDuration(200)
    if (build?.invoke(anim) != true) {
        anim.start()
    }
}

/**
 * 移除recyclerView光晕效果
 */
fun ViewPager2.overScrollNever() {
    this.children.forEach {
        if (it is RecyclerView) {
            it.overScrollMode = View.OVER_SCROLL_NEVER
        }
    }
}

/**
 * 设置角标
 */
@ExperimentalBadgeUtils
fun View.attachBadgeDawable(
    badgeDrawable: BadgeDrawable? = null,
    customBadgeParent: FrameLayout? = null
): BadgeDrawable {
    val drawable = badgeDrawable ?: BadgeDrawable.create(context)
    drawable.isVisible = true
    BadgeUtils.attachBadgeDrawable(drawable, this, customBadgeParent)
    return drawable
}

/**
 * 设置角标
 */
@ExperimentalBadgeUtils
fun Toolbar.attachBadgeDawable(
    @IdRes menuItemId: Int,
    badgeDrawable: BadgeDrawable? = null,
    customBadgeParent: FrameLayout? = null
): BadgeDrawable {
    val drawable = badgeDrawable ?: BadgeDrawable.create(context)
    drawable.isVisible = true
    BadgeUtils.attachBadgeDrawable(drawable, this, menuItemId, customBadgeParent)
    return drawable
}

/**
 * 移除角标
 */
@ExperimentalBadgeUtils
fun Toolbar.detachBadgeDawable(
    @IdRes menuItemId: Int,
    badgeDrawable: BadgeDrawable?,
) {
    BadgeUtils.detachBadgeDrawable(badgeDrawable, this, menuItemId)
}

/**
 * 移除角标
 */
@ExperimentalBadgeUtils
fun View.detachBadgeDawable(
    badgeDrawable: BadgeDrawable?,
) {
    BadgeUtils.detachBadgeDrawable(badgeDrawable, this)
}